Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(state-machine): Panic in the case of non-handled non-deferred e… #1464

Open
wants to merge 5 commits into
base: feature-c++-client
Choose a base branch
from

Conversation

oleorhagen
Copy link
Contributor

No description provided.

@mender-test-bot
Copy link

@oleorhagen, Let me know if you want to start the integration pipeline by mentioning me and the command "start pipeline".


my commands and options
You can trigger a pipeline on multiple prs with: - mentioning me and `start pipeline --pr mender/127 --pr mender-connect/255`

You can start a fast pipeline, disabling full integration tests with:

  • mentioning me and start pipeline --fast

You can trigger GitHub->GitLab branch sync with:

  • mentioning me and sync

You can cherry pick to a given branch or branches with:

  • mentioning me and:
 cherry-pick to:
 * 1.0.x
 * 2.0.x

@lluiscampos lluiscampos requested a review from kacf November 2, 2023 14:02
Copy link
Member

@kacf kacf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good safeguard!


// Check if there are any non-deferred events in the queue - then fail if
queue<EventType> queue_copy = event_queue_;
while (not queue_copy.empty()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's expected to have non-deferred events here, because this is after the handlers have run. I think the check needs to be between the if (!to_run.empty()) { block and the one above it.

There is also a much easier way to check this. When we are doing event_queue_.push(event) above, also increment a deferred_count counter. If deferred_count < event_queue_.size(), then the check is positive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Very good idea!

I had a suspicion you would come up with something smarter than me here 😆

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, new try. I am still using my original approach, but moved it to before we run the machine loop.

Ur approach, although clever, did not work when initializing (since we add the start events to the to_run queue, and I didn't feel like special casing it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be easily fixed too. Just keep a counter for the run_queue as well, but don't increment it during the initialization step, only when adding events in the "normal" flow. Then the check becomes deferred_count < added_to_run_queue. I think it's better than copying the whole queue on every state transition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I did dabble with the idea. But decided it's not really better. This implementation reads pretty straight forward, and does not have to touch the other pieces of code, and handle special cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying the queue should just be a couple of elements

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok then, I'll let it go! 🙂

@oleorhagen oleorhagen force-pushed the state-machine-non-deferred-events branch from 8966992 to 5f8c974 Compare November 30, 2023 13:37
@oleorhagen oleorhagen requested a review from kacf November 30, 2023 13:39
DBusError dbus_error;
dbus_error_init(&dbus_error);
dbus_conn_.reset(dbus_bus_get_private(DBUS_BUS_SYSTEM, &dbus_error));
std::unique_ptr<DBusError, void (*)(DBusError *)> dbus_error {new DBusError, dbus_error_free};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I support the incentive, but I suspect you have in fact have introduced a memory leak here. There are two levels of resources here, the DBusError struct itself, and the content it contains. dbus_error_free only frees the latter.

I can see two ways to solve it:

  1. Use a lambda with both dbus_error_free and delete dbus_error in it.
  2. Don't use new DBusError, but keep the variable on the stack instead, as before, and use &dbus_error as the argument when constructing the smart pointer (with a different name), together with dbus_error_free. The unique_ptr now doesn't own the pointer itself, but it owns the contents.

Same for the other commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh shite. True. Rookie mistake!


// Check if there are any non-deferred events in the queue - then fail if
queue<EventType> queue_copy = event_queue_;
while (not queue_copy.empty()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be easily fixed too. Just keep a counter for the run_queue as well, but don't increment it during the initialization step, only when adding events in the "normal" flow. Then the check becomes deferred_count < added_to_run_queue. I think it's better than copying the whole queue on every state transition.

Just makes it more future proof, as we don't have to remember free it in our
exit paths anylonger.

Signed-off-by: Ole Petter <[email protected]>
This just makes this consistent with the rest of our codebase.

Signed-off-by: Ole Petter <[email protected]>
Simply split out and name the logical parts.

Signed-off-by: Ole Petter <[email protected]>
…vents

This adds a sanity check to verify that there are no non-deferred events left in
the event queue after the run_queue has been populated.

If there was, then we would have undefined behaviour in the state-machine, and
as such the best thing we can do in this instance is to panic. This is a serious
logic error in our code, and as such such cause a hard-fault.

Signed-off-by: Ole Petter <[email protected]>
@oleorhagen oleorhagen force-pushed the state-machine-non-deferred-events branch from 5f8c974 to 9cad8e7 Compare December 4, 2023 12:47
+ dbus_error.name + "]");
dbus_error_free(&dbus_error);
string("Failed to get connection to system bus: ") + dbus_error.get()->message + "["
+ dbus_error.get()->name + "]");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.get() should only be used when it's required to, here it can be omitted.

Copy link

stale bot commented Mar 17, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Mar 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants